package com.sita.cfmoto.utils;

import android.graphics.Color;
import android.support.annotation.NonNull;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.amap.api.maps.model.LatLng;
import com.google.gson.reflect.TypeToken;
import com.kymjs.rxvolley.RxVolley;
import com.kymjs.rxvolley.client.HttpCallback;
import com.kymjs.rxvolley.client.HttpParams;
import com.sita.cfmoto.ErrorCode;
import com.sita.cfmoto.beans.VehicleBean;
import com.sita.cfmoto.rest.RestClient;
import com.sita.cfmoto.rest.model.BindedVehicle;
import com.sita.cfmoto.rest.model.RestResponse;
import com.sita.cfmoto.rest.model.Vehicle;
import com.sita.cfmoto.rest.model.VehicleData;
import com.sita.cfmoto.rest.model.request.BindVehicleRequest;
import com.sita.cfmoto.rest.model.request.CfmotorCommonRequest;
import com.sita.cfmoto.rest.model.request.FetchBindVehiclesRequest;
import com.sita.cfmoto.rest.model.request.FetchVehicleBatteryHistoryRequest;
import com.sita.cfmoto.rest.model.request.FetchVehicleDataRequest;
import com.sita.cfmoto.rest.model.request.FetchVehicleDriveHistoryRequest;
import com.sita.cfmoto.rest.model.request.ListVehicleIdRequest;
import com.sita.cfmoto.rest.model.request.RepairFetchRequest;
import com.sita.cfmoto.rest.model.request.SetBatteryAlarmRequest;
import com.sita.cfmoto.rest.model.request.SetGeoFenceRequest;
import com.sita.cfmoto.rest.model.request.UnbindVehicleRequest;
import com.sita.cfmoto.rest.model.response.BatteryAlarmResponse;
import com.sita.cfmoto.rest.model.response.FetchVehicleBatteryHistoryResponse;
import com.sita.cfmoto.rest.model.response.FetchVehicleDriveDayDataResponse;
import com.sita.cfmoto.rest.model.response.FetchVehicleDriveHistoryResponse;
import com.sita.cfmoto.rest.model.response.FetchVehicleDriveMonthDataResponse;
import com.sita.cfmoto.rest.model.response.GeofenceResponse;
import com.sita.cfmoto.rest.model.response.RepairStore;
import com.sita.cfmoto.rest.model.response.VehicleYadeaFaultResponse;
import com.sita.cfmoto.support.Constants;

import java.util.ArrayList;
import java.util.List;

import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;

/**
 * Created by mark man on 2016/5/17.
 */
public class VehicleUtils {

    public static final int EMOTION_LIGHT_SETTING_OK = 0;
    public static final int EMOTION_LIGHT_SETTING_FAIL = 1;
    public static final int EMOTION_LIGHT_SETTING_DISCARD = 2;
    private final static String TAG = VehicleUtils.class.getSimpleName();
    public static long DEFAULT_GPS_VENDOR = 1;
    // 车状态 0：设防，1：撤防不上电，2：驻车，3 ：行车
    public static int CAR_STATUS_LOCKED = 0;
    public static int CAR_STATUS_UNLOCKED = 1;
    public static int CAR_STAY = 2;
    public static int CAR_STATUS_MOVE = 3;
    public static boolean mLocked = false;
    public static boolean mCanLocked = true;
    public static boolean mEngineStart = false;
    public static boolean mNotificationOpen = false;
    public static boolean mDashboardPowerMode = false;
    public static boolean mIsWhiteColor = true;
    public static boolean mKeyInSide = false;
    public static VehicleBean vehicleBean; // TODO: 2016/5/21 should build vehicle list
    public static int mPreviousMode = 0;
    public static long mLastVehicleStatusTime = 0;
    private static int mStatus;
    private static int mLastSelectedEmotionColor = Color.GREEN;
    private static boolean mIsWorkaroundBluetooth = false;
    private static int mSmartLightDelayTime = 5;
    private static int mSmartLightBeginTime = 0;
    private static int mSmartLightEndTime = 0;
    private static Float nearStoreLat = null;
    private static Float nearStoreLng = null;
    private static BindedVehicle currentSelectedVehicle;
    private static boolean hasInitRikySDK = false;

    static {
        initVehicleBean();
    }

    public static String getVin() {
        return vehicleBean.vin;
    }

    public static int getSnCpy() {
        return vehicleBean.cpy;
    }

    static void initVehicleBean() {

        LogUtils.d("initVehicleBean", "1");
        vehicleBean = PersistUtils.selectVehicleBean(LocalStorage.getAccountId(), false);
        if (vehicleBean == null) {
            LogUtils.d("initVehicleBean", "2");
            vehicleBean = PersistUtils.selectVehicleBean(LocalStorage.getAccountId(), true);
        }
        if (vehicleBean == null) {
            LogUtils.d("initVehicleBean", "3");
            vehicleBean = new VehicleBean();
        }
    }

    public static void resetVehicleBean() {
        if (vehicleBean != null) {
            vehicleBean = null;
        }
        vehicleBean = new VehicleBean();
    }

    public static void resetRealTimeData() {

    }


    public static BindedVehicle getCurrentSelectedVehicle() {
        String sn = LocalStorage.getCurrSelectedVehicle();
        if (android.text.TextUtils.isEmpty(sn)) {
            List<BindedVehicle> vehicles = PersistUtils.getBindedVehicles();
            if (vehicles == null || vehicles.isEmpty()) {
                return null;
            } else {
                currentSelectedVehicle = vehicles.get(0);
                LocalStorage.setCurrSelectedVehicle(currentSelectedVehicle.vin);

                setVehicleBean(currentSelectedVehicle); // must copying the data into vehiclebean memory;
                return currentSelectedVehicle;
            }
        }
        if (currentSelectedVehicle == null) {
            currentSelectedVehicle = PersistUtils.getBindedVehicle(sn);
            if (currentSelectedVehicle == null) {
                return null;
            }
        }
        if (!currentSelectedVehicle.vin.equals(sn)) {
            currentSelectedVehicle = PersistUtils.getBindedVehicle(sn);
        }
        setVehicleBean(currentSelectedVehicle); // must copying the data into vehiclebean memory;
        return currentSelectedVehicle;
    }

    public static void setCurrentSelectedVehicle(String snId) {
        LocalStorage.setCurrSelectedVehicle(snId);
        getCurrentSelectedVehicle();
    }

    private static void setVehicleBean(BindedVehicle bindedVehicle) {
        vehicleBean.vin = bindedVehicle.vin;
        vehicleBean.vinpwd = bindedVehicle.password;
        vehicleBean.cpy = (int) bindedVehicle.vincpy;
//        vehicleBean.controllerAddr = bindedVehicle.controllerAddress;
//        vehicleBean.controllerKey = bindedVehicle.controllerPassword;
        vehicleBean.accountId = bindedVehicle.userId;

    }


    public static void fetchVehicleDriveMonthState(FetchVehicleDriveMonthStateListener listener) {
        CfmotorCommonRequest paramsJson = new CfmotorCommonRequest();
        paramsJson.vin = VehicleUtils.vehicleBean.vin;
        paramsJson.vinCpy = VehicleUtils.vehicleBean.cpy;

        RestClient.getRestService().fetchVehicleDriveMonthState(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0")) {
                    String str = RestClient.getGson().toJson(restResponse.mData);
                    FetchVehicleDriveMonthDataResponse data = RestClient.getGson().fromJson(str, FetchVehicleDriveMonthDataResponse.class);
                    if (listener != null) {
                        listener.onSuccess(data);
                    }
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "get vehicle data error!!!");
            }
        });
    }

    public static void fetchVehicleDriveDayState(FetchVehicleDriveDayStateListener listener) {
        CfmotorCommonRequest paramsJson = new CfmotorCommonRequest();
        paramsJson.vin = VehicleUtils.vehicleBean.vin;
        paramsJson.vinCpy = VehicleUtils.vehicleBean.cpy;

        RestClient.getRestService().fetchVehicleDriveDayState(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0")) {
                    String str = RestClient.getGson().toJson(restResponse.mData);
                    FetchVehicleDriveDayDataResponse data = RestClient.getGson().fromJson(str, FetchVehicleDriveDayDataResponse.class);
                    if (listener != null) {
                        listener.onSuccess(data);
                    }
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "get vehicle data error!!!");
            }
        });
    }

    public static void fetchVehicleDriveHistoryState(FetchVehicleDriveHistoryListener listener, int pageNumber) {
        FetchVehicleDriveHistoryRequest paramsJson = new FetchVehicleDriveHistoryRequest();
        paramsJson.vin = VehicleUtils.vehicleBean.vin;
        paramsJson.vinCpy = VehicleUtils.vehicleBean.cpy;
        paramsJson.pageNumber = pageNumber;
        paramsJson.pageSize = 5;

        RestClient.getRestService().fetchVehicleDriveHistory(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0")) {
                    String str = RestClient.getGson().toJson(restResponse.mData);
                    List<FetchVehicleDriveHistoryResponse> data = RestClient.getGson().fromJson(str, new TypeToken<List<FetchVehicleDriveHistoryResponse>>() {
                    }.getType());
                    if (listener != null) {
                        listener.onSuccess(data);
                    }
                } else {
                    if (listener != null) {
                        listener.onSuccess(null);
                    }
                }

            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "get vehicle data error!!!");
                if (listener != null) {
                    listener.onSuccess(null);
                }
            }
        });
    }

//    public static void fetchNearestRepairStore() {
//        RepairFetchRequest paramsJson = new RepairFetchRequest();
//        paramsJson.sn = VehicleUtils.vehicleBean.vin;
//        paramsJson.sncpy = VehicleUtils.vehicleBean.cpy;
//
//        paramsJson.lat = VehicleUtils.vehicleBean.lat;
//        paramsJson.lng = VehicleUtils.vehicleBean.lng;
//        paramsJson.distance = 20; // // TODO: 2016/6/6
//
//        RestClient.getRestService().fetchRepairStores(paramsJson, new Callback<RestResponse>() {
//            @Override
//            public void success(RestResponse restResponse, Response response) {
//                if (response.getStatus() == 200 && restResponse.mErrorCode.equals("0")) {
//                    try {
//                        String s = RestClient.getGson().toJson(restResponse.mData);
//                        List<RepairStore> stores = RestClient.getGson().fromJson(s, new TypeToken<List<RepairStore>>() {
//                        }.getType());
//                        if (stores.size() > 0) {
//                            EventBus.getDefault().post(new FetchRepairStatusEvent(stores.subList(0, 1)));
//                        } else {
//                            EventBus.getDefault().post(new FetchRepairStatusEvent(null));
//                        }
//                    } catch (Exception e) {
//                        EventBus.getDefault().post(new FetchRepairStatusEvent(null));
//                    }
//
//                }
//            }
//
//            @Override
//            public void failure(RetrofitError error) {
//                LogUtils.d(TAG, "get vehicle location error!!!");
//                EventBus.getDefault().post(new FetchRepairStatusEvent(null));
//            }
//        });
//    }

//    public static void fetchSpeed() {
//        RikyInfoBtUtils.getVehicleStatus(new RikyInfoBtUtils.OnVehicleStatusListener() {
//            @Override
//            public void onSuccess(VehicleStatus vehicleStatus) {
//                EventBus.getDefault().post(new SpeedFetchEvent(vehicleStatus.getSpeed()));
//            }
//
//            @Override
//            public void onFail(Throwable throwable) {
//
//            }
//        });
//    }

    public static void fetchVehicleBatteryHistoryState(FetchVehicleBatteryHistoryListener listener, int pageNumber) {
        FetchVehicleBatteryHistoryRequest paramsJson = new FetchVehicleBatteryHistoryRequest();
        paramsJson.vin = VehicleUtils.vehicleBean.vin;
        paramsJson.vinCpy = VehicleUtils.vehicleBean.cpy;
        paramsJson.pageNumber = pageNumber;
        paramsJson.pageSize = 5;

        RestClient.getRestService().fetchVehicleBatteryHistory(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0")) {
                    String str = RestClient.getGson().toJson(restResponse.mData);
                    List<FetchVehicleBatteryHistoryResponse> data = RestClient.getGson().fromJson(str, new TypeToken<List<FetchVehicleBatteryHistoryResponse>>() {
                    }.getType());
                    if (listener != null) {
                        listener.onSuccess(data);
                    }
                } else {
                    if (listener != null) {
                        listener.onSuccess(null);
                    }
                }

            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "get vehicle data error!!!");
                if (listener != null) {
                    listener.onSuccess(null);
                }
            }
        });
    }

    public static void fetchMaintShopsByDistance(LatLng latLng, int distance, final FetchRepairStoresCallback callback) {
//        BindedVehicle vehicle = getCurrentSelectedVehicle();
        RepairFetchRequest paramsJson = new RepairFetchRequest();
//        paramsJson.sn = vehicle.vin;
//        paramsJson.sncpy = vehicle.vincpy;
        paramsJson.lat = latLng.latitude;
        paramsJson.lng = latLng.longitude;
        paramsJson.distance = distance;

        RestClient.getRestService().fetchRepairStores(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (response.getStatus() == 200 && restResponse.mErrorCode.equals("0")) {
                    try {
                        String s = RestClient.getGson().toJson(restResponse.mData);
                        List<RepairStore> stores = RestClient.getGson().fromJson(s, new TypeToken<List<RepairStore>>() {
                        }.getType());
                        callback.onRepairStoresFetched(stores);
                    } catch (Exception e) {
                        callback.onRepairStoresFetched(new ArrayList<RepairStore>());
                    }
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "get vehicle location error!!!");
                callback.onRepairStoresFetched(null);
            }
        });
    }

    /**
     * 从本地获取, 登录后使用
     */
    public static List<BindedVehicle> getBindedVehicles() {
        List<BindedVehicle> bindedVehicles = PersistUtils.getBindedVehicles();
        return bindedVehicles;
    }

    /**
     * 从网络获取, 同步时使用
     *
     * @param callback
     */
    public static void fetchBindedVehicles(final FetchBindedVehiclesCallback callback) {
        FetchBindVehiclesRequest request = new FetchBindVehiclesRequest();
        request.userId = LocalStorage.getAccountId();
        String jsonParam = JSONObject.toJSONString(request);

        String url = Constants.BASE_URI + "/cfmotor/v1/machines/machine/bind/list";

        HttpParams params = new HttpParams();
        params.putJsonParams(jsonParam);

        //http请求的回调，内置了很多方法，详细请查看源码
        //包括在异步响应的onSuccessInAsync():注不能做UI操作
        //网络请求成功时的回调onSuccess()
        //网络请求失败时的回调onFailure():例如无网络，服务器异常等
        HttpCallback httpCallback = new HttpCallback() {
            @Override
            public void onSuccess(String t) {
                JSONObject rootObj = JSONObject.parseObject(t);
                String errorCode = rootObj.getString("errorCode");
                if ("0".equals(errorCode)) {
                    String dataString = rootObj.getString("data");
                    List<BindedVehicle> bindedVehicles = JSONObject.parseObject(dataString,
                            new TypeReference<List<BindedVehicle>>() {
                            });

                    if (bindedVehicles != null && !bindedVehicles.isEmpty()) {
                        // need to clear the old current user's data rows
                        PersistUtils.deleteUserAllBindedVehicle(LocalStorage.getAccountId());
                        PersistUtils.saveBindedVehicles(bindedVehicles);
                    }

                    callback.onBindedVehiclesFetched(bindedVehicles);
                }
            }

            @Override
            public void onFailure(int errorNo, String strMsg) {
                L.e("fetchBindedVehicles() --> get error code " + errorNo + ", " + strMsg);
                callback.onBindedVehiclesFetched(null);
            }
        };

        new RxVolley.Builder()
                .url(url) //接口地址
                //请求类型，如果不加，默认为 GET 可选项：
                //POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH
                .httpMethod(RxVolley.Method.POST)
                //设置缓存时间: 默认是 get 请求 5 分钟, post 请求不缓存
                //.cacheTime(0)
                //内容参数传递形式，如果不加，默认为 FORM 表单提交，可选项 JSON 内容
                .contentType(RxVolley.ContentType.JSON)
                .params(params) //上文创建的HttpParams请求参数集
                //是否缓存，默认是 get 请求 5 缓存分钟, post 请求不缓存
                .shouldCache(false)
                .callback(httpCallback) //响应回调
                .encoding("UTF-8") //编码格式，默认为utf-8
                .doTask();  //执行请求操作
    }

    public static void bindVehicle(BindedVehicle vehicle, final BindVehicleCallback callback) {
        BindVehicleRequest request = new BindVehicleRequest();
        request.userId = Long.valueOf(LocalStorage.getAccountId());
        Log.e("用户userid", String.valueOf(request.userId));
        request.vinId = vehicle.vin;
        request.vinCpy = vehicle.vincpy;
        request.vinPassword = vehicle.password;
        RestClient.getRestService().bindVehicle(request, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                LogUtils.d(TAG, "bind success");
                if (restResponse.mErrorCode.equals("0")) {
                    callback.onBindVehicleSuccess(vehicle.vin);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "get binded vehicles error!!!");
                Throwable throwable = error;
                RestResponse restResponse = (RestResponse) error.getBodyAs(RestResponse.class);
                if (restResponse == null) {
                    ToastTool.showDebugMessage("请检查网络");
                } else {
                    if (restResponse.mErrorCode.equals(ErrorCode.VEHICLE_SN_NOT_EXIST)) {
                        throwable = new Exception("车架号不存在");
                    } else if (restResponse.mErrorCode.equals(ErrorCode.VEHICLE_SNPASSWORD_WRONG)) {
                        throwable = new Exception("车架号密码错误");
                    }

                    callback.onBindVehicleFailed(throwable);
                }
            }
        });
    }

    public static void unbindVehicle(BindedVehicle vehicle, final UnbindVehicleCallback callback) {
        UnbindVehicleRequest request = new UnbindVehicleRequest();
        request.vinId = vehicle.vin;
        request.vinCpy = vehicle.vincpy;
        request.userId = vehicle.userId;

        String jsonParam = JSONObject.toJSONString(request);

        String url = Constants.BASE_URI + "/cfmotor/v1/machines/machine/unbind/machine";

        HttpParams params = new HttpParams();
        params.putJsonParams(jsonParam);

        //http请求的回调，内置了很多方法，详细请查看源码
        //包括在异步响应的onSuccessInAsync():注不能做UI操作
        //网络请求成功时的回调onSuccess()
        //网络请求失败时的回调onFailure():例如无网络，服务器异常等
        HttpCallback httpCallback = new HttpCallback() {
            @Override
            public void onSuccess(String t) {
                JSONObject rootObj = JSONObject.parseObject(t);
                String errorCode = rootObj.getString("errorCode");
                if ("0".equals(errorCode)) {
                    callback.onUnbindVehicleResult(true);
                }
            }

            @Override
            public void onFailure(int errorNo, String strMsg) {
                L.e("unbindVehicle() --> get error code " + errorNo + ", " + strMsg);
                callback.onUnbindVehicleResult(false);
            }
        };

        new RxVolley.Builder()
                .url(url) //接口地址
                //请求类型，如果不加，默认为 GET 可选项：
                //POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH
                .httpMethod(RxVolley.Method.POST)
                //设置缓存时间: 默认是 get 请求 5 分钟, post 请求不缓存
                //.cacheTime(0)
                //内容参数传递形式，如果不加，默认为 FORM 表单提交，可选项 JSON 内容
                .contentType(RxVolley.ContentType.JSON)
                .params(params) //上文创建的HttpParams请求参数集
                //是否缓存，默认是 get 请求 5 缓存分钟, post 请求不缓存
                .shouldCache(false)
                .callback(httpCallback) //响应回调
                .encoding("UTF-8") //编码格式，默认为utf-8
                .doTask();  //执行请求操作
    }

    public static void fetchBindedVehicle(String sn, long snCpy, String password, final FetchBindedVehicleCallback callback) {
        ListVehicleIdRequest request = new ListVehicleIdRequest();
        request.sn = sn;
        request.sncpy = snCpy;
        request.snpassword = password;

        String jsonParam = JSONObject.toJSONString(request);

        String url = Constants.BASE_URI + "/cfmotor/v1/machines//machine/sn/list";

        HttpParams params = new HttpParams();
        params.putJsonParams(jsonParam);

        HttpCallback httpCallback = new HttpCallback() {
            @Override
            public void onSuccess(String t) {
                JSONObject rootObj = JSONObject.parseObject(t);
                String errorCode = rootObj.getString("errorCode");
                String dataString = rootObj.getString("data");
                if ("0".equals(errorCode)) {
                    if (dataString == null) {
                        callback.onFetchBindedVehicle(null);
                        return;
                    }

                    Vehicle vehicle = JSONObject.parseObject(dataString, Vehicle.class);
                    BindedVehicle bv = new BindedVehicle();
                    if (vehicle != null) {
                        bv.userId = LocalStorage.getAccountId();
                        bv.vin = vehicle.vin;
                        bv.vincpy = vehicle.vincpy;
                        bv.password = vehicle.password;
                        bv.machineType = vehicle.machineType;
                        bv.mcuid = vehicle.mcuid;
                        bv.iccid = vehicle.iccid;
                        bv.imsi = vehicle.imsi;
                        bv.imei = vehicle.imei;
                        bv.dealerId = vehicle.dealerId;
                        bv.hardWareCode = vehicle.hardWareCode;
                        bv.softWareCode = vehicle.softWareCode;
                        bv.vproto = vehicle.vproto;
                        bv.terminalId = vehicle.terminalId;
                        bv.seeds = vehicle.seeds;
                        bv.imeicpy = vehicle.imeicpy;
                        bv.doTime = vehicle.doTime;
                        bv.machineStatus = vehicle.machineStatus;
                        bv.machineKind = vehicle.machineKind;
                        if (bv != null) {
                            PersistUtils.saveBindedVehicle(bv);
                        }
                    }


                    callback.onFetchBindedVehicle(bv);
                }
            }

            @Override
            public void onFailure(int errorNo, String strMsg) {
                L.e("fetchBindedVehicles() --> get error code " + errorNo + ", " + strMsg);
                callback.onFetchBindedVehicle(null);
            }
        };

        new RxVolley.Builder()
                .url(url) //接口地址
                //请求类型，如果不加，默认为 GET 可选项：
                //POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH
                .httpMethod(RxVolley.Method.POST)
                //设置缓存时间: 默认是 get 请求 5 分钟, post 请求不缓存
                //.cacheTime(0)
                //内容参数传递形式，如果不加，默认为 FORM 表单提交，可选项 JSON 内容
                .contentType(RxVolley.ContentType.JSON)
                .params(params) //上文创建的HttpParams请求参数集
                //是否缓存，默认是 get 请求 5 缓存分钟, post 请求不缓存
                .shouldCache(false)
                .callback(httpCallback) //响应回调
                .encoding("UTF-8") //编码格式，默认为utf-8
                .doTask();  //执行请求操作
    }

    public static void fetchBindedVehicleWithoutSave(String sn, long snCpy, String password, final FetchBindedVehicleCallback callback) {
        ListVehicleIdRequest request = new ListVehicleIdRequest();
        request.sn = sn;
        request.sncpy = snCpy;
        request.snpassword = password;

        String jsonParam = JSONObject.toJSONString(request);

        String url = Constants.BASE_URI + "/cfmotor/v1/machines//machine/sn/list";

        HttpParams params = new HttpParams();
        params.putJsonParams(jsonParam);

        HttpCallback httpCallback = new HttpCallback() {
            @Override
            public void onSuccess(String t) {
                JSONObject rootObj = JSONObject.parseObject(t);
                String errorCode = rootObj.getString("errorCode");
                String dataString = rootObj.getString("data");
                if ("0".equals(errorCode)) {
                    if (dataString == null) {
                        callback.onFetchBindedVehicle(null);
                        return;
                    }

                    Vehicle vehicle = JSONObject.parseObject(dataString, Vehicle.class);
                    BindedVehicle bv = new BindedVehicle();
                    if (vehicle != null) {
                        bv.userId = LocalStorage.getAccountId();
                        bv.vin = vehicle.vin;
                        bv.vincpy = vehicle.vincpy;
                        bv.password = vehicle.password;
                        bv.machineType = vehicle.machineType;
                        bv.mcuid = vehicle.mcuid;
                        bv.iccid = vehicle.iccid;
                        bv.imsi = vehicle.imsi;
                        bv.imei = vehicle.imei;
                        bv.dealerId = vehicle.dealerId;
                        bv.hardWareCode = vehicle.hardWareCode;
                        bv.softWareCode = vehicle.softWareCode;
                        bv.vproto = vehicle.vproto;
                        bv.terminalId = vehicle.terminalId;
                        bv.seeds = vehicle.seeds;
                        bv.imeicpy = vehicle.imeicpy;
                        bv.doTime = vehicle.doTime;
                        bv.machineStatus = vehicle.machineStatus;
                        bv.machineKind = vehicle.machineKind;
                    }
                    callback.onFetchBindedVehicle(bv);
                }
            }

            @Override
            public void onFailure(int errorNo, String strMsg) {
                L.e("fetchBindedVehicles() --> get error code " + errorNo + ", " + strMsg);
                callback.onFetchBindedVehicle(null);
            }
        };

        new RxVolley.Builder()
                .url(url) //接口地址
                //请求类型，如果不加，默认为 GET 可选项：
                //POST/PUT/DELETE/HEAD/OPTIONS/TRACE/PATCH
                .httpMethod(RxVolley.Method.POST)
                //设置缓存时间: 默认是 get 请求 5 分钟, post 请求不缓存
                //.cacheTime(0)
                //内容参数传递形式，如果不加，默认为 FORM 表单提交，可选项 JSON 内容
                .contentType(RxVolley.ContentType.JSON)
                .params(params) //上文创建的HttpParams请求参数集
                //是否缓存，默认是 get 请求 5 缓存分钟, post 请求不缓存
                .shouldCache(false)
                .callback(httpCallback) //响应回调
                .encoding("UTF-8") //编码格式，默认为utf-8
                .doTask();  //执行请求操作
    }

    public static void fetchFault(@NonNull OnFetchFaultListener listener) {
        fetchFaultByCloud(listener);
    }

    private static void fetchFaultByCloud(@NonNull OnFetchFaultListener listener) {
        CfmotorCommonRequest paramsJson = new CfmotorCommonRequest();
        paramsJson.vin = VehicleUtils.vehicleBean.vin;
        paramsJson.vinCpy = VehicleUtils.vehicleBean.cpy;

        RestClient.getRestService().getFault(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0") && restResponse.mData != null) {
                    String str = RestClient.getGson().toJson(restResponse.mData);
                    VehicleYadeaFaultResponse status = RestClient.getGson().fromJson(str, VehicleYadeaFaultResponse.class);
                    listener.onResult(status.isOk());
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "get vehicle status error!!!");
            }
        });
    }


    public static void updateLocation(LatLng latLng) {
        vehicleBean.lat = latLng.latitude;
        vehicleBean.lng = latLng.longitude;
    }

    public static void getGeofenceSetting(FetchGeofenceSettingCallback listener) {
        CfmotorCommonRequest paramsJson = new CfmotorCommonRequest();
        paramsJson.vin = VehicleUtils.vehicleBean.vin;
        paramsJson.vinCpy = VehicleUtils.vehicleBean.cpy;

        RestClient.getRestService().getGeofence(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0") && restResponse.mData != null) {
                    String str = RestClient.getGson().toJson(restResponse.mData);
                    GeofenceResponse res = RestClient.getGson().fromJson(str, GeofenceResponse.class);
                    // TODO: 2016/7/13 check 0,0
                    if (Double.compare(res.lat, 0d) == 0 && Double.compare(res.lng, 0d) == 0) {
                        listener.onResult(false, false, 0, 0, 0);
                    } else {
                        listener.onResult(true, res.set == 0, res.lat, res.lng, res.distance);
                    }
                }
                if (restResponse.mErrorCode.equals("0") && restResponse.mData == null) {
                    listener.onResult(false, false, 0, 0, 0);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "getGeofence error!!!");
                listener.onResult(false, false, 0, 0, 0);
            }
        });
    }

    public static void setGeofence(OnResultListener listener, double lat, double lng, int distance, boolean enabled) {
        SetGeoFenceRequest paramsJson = new SetGeoFenceRequest();
        paramsJson.sn = VehicleUtils.vehicleBean.vin;
        paramsJson.sncpy = VehicleUtils.vehicleBean.cpy;
        paramsJson.lat = lat;
        paramsJson.lng = lng;
        paramsJson.distance = distance;
        paramsJson.enabled = enabled ? 0 : 1;

        RestClient.getRestService().setGeofence(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0")) {
                    listener.onResult(true);
                } else {
                    listener.onResult(false);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "setGeofence error!!!");
                listener.onResult(false);
            }
        });
    }

    public static void getBatterySetting(FetchBatteryAlarmSettingCallback listener) {
        CfmotorCommonRequest paramsJson = new CfmotorCommonRequest();
        paramsJson.vin = VehicleUtils.vehicleBean.vin;
        paramsJson.vinCpy = VehicleUtils.vehicleBean.cpy;

        RestClient.getRestService().getBatteryAlarm(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0") && restResponse.mData != null) {
                    String str = RestClient.getGson().toJson(restResponse.mData);
                    BatteryAlarmResponse res = RestClient.getGson().fromJson(str, BatteryAlarmResponse.class);
                    listener.onResult(true, res.enabled == 0, res.soc);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "getBatteryAlarm error!!!");
            }
        });
    }

//    private static boolean mIsSettingEmotion = false;

    public static void setBatterySetting(OnResultListener listener, int soc, boolean enabled) {
        SetBatteryAlarmRequest paramsJson = new SetBatteryAlarmRequest();
        paramsJson.sn = VehicleUtils.vehicleBean.vin;
        paramsJson.sncpy = VehicleUtils.vehicleBean.cpy;
        paramsJson.soc = soc;
        paramsJson.enabled = enabled ? 0 : 1;

        RestClient.getRestService().setBatteryAlarm(paramsJson, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0")) {
                    listener.onResult(true);
                } else {
                    listener.onResult(false);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                LogUtils.d(TAG, "setBatteryAlarm error!!!");
                listener.onResult(false);
            }
        });
    }

    public static void FetchVehicleData(FetchVehicleDataCallback callback) {
        BindedVehicle bindedVehicle = VehicleUtils.getCurrentSelectedVehicle();
        if (bindedVehicle == null) {
            return;
        }
        FetchVehicleDataRequest request = new FetchVehicleDataRequest();
        request.sn = bindedVehicle.vin;
        request.sncpy = bindedVehicle.vincpy;
        RestClient.getRestService().fetchVehicleData(request, new Callback<RestResponse>() {
            @Override
            public void success(RestResponse restResponse, Response response) {
                if (restResponse.mErrorCode.equals("0")) {
                    String str = RestClient.getGson().toJson(restResponse.mData);
                    VehicleData vehicleData = RestClient.getGson().fromJson(str, VehicleData.class);
                    callback.onVehicleDataFetched(vehicleData);
                }
            }

            @Override
            public void failure(RetrofitError error) {
                callback.onVehicleDataFetched(null);
            }
        });

    }

    public interface FetchVehicleLocationCallback {
        void onVehicleLocationFetched(LatLng latLng);
    }

    public interface FetchVehicleDriveMonthStateListener {
        void onSuccess(FetchVehicleDriveMonthDataResponse response);
    }

    public interface FetchVehicleDriveDayStateListener {
        void onSuccess(FetchVehicleDriveDayDataResponse response);
    }

    public interface FetchVehicleDriveHistoryListener {
        void onSuccess(List<FetchVehicleDriveHistoryResponse> list);
    }

    public interface FetchVehicleBatteryHistoryListener {
        void onSuccess(List<FetchVehicleBatteryHistoryResponse> list);
    }

    public interface FetchRepairStoresCallback {
        void onRepairStoresFetched(List<RepairStore> stores);
    }

    public interface FetchBindedVehiclesCallback {
        void onBindedVehiclesFetched(List<BindedVehicle> vehicles);
    }

    public interface BindVehicleCallback {
        void onBindVehicleSuccess(String vehicleSn);

        void onBindVehicleFailed(Throwable cause);
    }


    public interface UnbindVehicleCallback {
        void onUnbindVehicleResult(boolean isOk);
    }

    public interface OnEmotionLightSettingListener {
        void onResult(int result);
    }

    public interface FetchBindedVehicleCallback {
        void onFetchBindedVehicle(BindedVehicle vehicle);
    }

    public interface OnFetchFaultListener {
        void onResult(boolean good);
    }

    public interface FetchGeofenceSettingCallback {
        void onResult(boolean result, boolean set, double lat, double lng, int range);
    }

    public interface OnResultListener {
        void onResult(boolean result);
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    public interface FetchBatteryAlarmSettingCallback {
        void onResult(boolean result, boolean set, int level);
    }

    public interface FetchVehicleDataCallback {
        void onVehicleDataFetched(VehicleData vehicleData);
    }
}
